/**************************************************************************************************
	$Header: /pub/cvsroot/mydns/src/mydns/error.c,v 1.16 2003/07/25 09:26:45 bboy Exp $

	Copyright (C) 2002, 2003  Don Moore <bboy@bboy.net>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at Your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**************************************************************************************************/

#include "named.h"


/**************************************************************************************************
	ERR_REASON_STR
	Returns a string describing 'reason'.
**************************************************************************************************/
char *
err_reason_str(task_error_t reason)
{
	switch (reason)
	{
		case ERR_NONE: return ("-");
		case ERR_ZONE_NOT_FOUND: return ((char *)_("Zone_not_found"));
		case ERR_NO_MATCHING_RECORDS: return ((char *)_("No_matching_resource_records"));
		case ERR_NO_AXFR: return ((char *)_("AXFR_disabled"));
		case ERR_RR_NAME_TOO_LONG: return ((char *)_("Name_too_long_in_RR"));
		case ERR_RR_LABEL_TOO_LONG: return ((char *)_("Label_too_long_in_RR"));
		case ERR_Q_BUFFER_OVERFLOW: return ((char *)_("Input_name_buffer_overflow"));
		case ERR_Q_INVALID_COMPRESSION: return ((char *)_("Invalid_compression_method"));
		case ERR_Q_NAME_TOO_LONG: return ((char *)_("Question_name_too_long"));
		case ERR_NO_CLASS: return ((char *)_("Unknown_class"));
		case ERR_NAME_FORMAT: return ((char *)_("Invalid_name_format"));
		case ERR_TIMEOUT: return ((char *)_("Communications_timeout"));
		case ERR_BROKEN_GLUE: return ((char *)_("Malformed_glue"));
		case ERR_INVALID_ADDRESS: return ((char *)_("Invalid_address"));
		case ERR_DB_ERROR: return ((char *)_("Database_error"));
		case ERR_NO_QUESTION: return ((char *)_("No_question_in_query"));
		case ERR_QUESTION_TRUNCATED: return ((char *)_("Question_truncated"));
		case ERR_UNSUPPORTED_OPCODE: return ((char *)_("Unsupported_opcode"));
		case ERR_MALFORMED_REQUEST: return ((char *)_("Malformed_request"));
		case ERR_AXFR_NOT_ENABLED: return ((char *)_("AXFR_not_enabled"));
		case ERR_TCP_NOT_ENABLED: return ((char *)_("TCP_not_enabled"));
	}
	return ((char *)_("Unknown"));
}
/*--- err_reason_str() --------------------------------------------------------------------------*/


/**************************************************************************************************
	_FORMERR_INTERNAL
	Called during parsing of request if an error occurs.
**************************************************************************************************/
int
_formerr_internal(
	TASK *t,					/* The failed task */
	dns_rcode_t rcode,	/* The return code to use, such as DNS_R_SERVFAIL, etc. */
	task_error_t reason,	/* Further explanation of the error */
	const char *filename,
	unsigned int lineno
)
{
	char	*dest;
	register TASK *task;
	int need_enqueue;

#if DEBUG_ENABLED
	Debug("%s: formerr(): %s %s from %s:%u",
			desctask(t), mydns_rcode_str(rcode), err_reason_str(reason), filename, lineno);
#endif

	/* See if task needs to be enqueued */
	for (task = Tasks->head, need_enqueue = 1; task && need_enqueue; task = task->next)
		if (task == t)
			need_enqueue = 0;

	if (need_enqueue && (enqueue(Tasks, t) < 0))
	{
		task_free(t);
		return (-1);
	}

	t->hdr.rcode = rcode;
	t->status = NEED_WRITE;
	t->reason = reason;

	/* Build simple reply to avoid problems with malformed data */
	t->replylen = DNS_HEADERSIZE;
	dest = t->reply = malloc(t->replylen);
	if (!t->reply)
		Err("malloc");
	t->hdr.qr = 1;
	DNS_PUT16(dest, t->id);										/* Query ID */
	DNS_PUT(dest, &t->hdr, SIZE16);							/* Header */
	DNS_PUT16(dest, 0);											/* QUESTION count */
	DNS_PUT16(dest, 0);											/* ANSWER count */
	DNS_PUT16(dest, 0);											/* AUTHORITY count */
	DNS_PUT16(dest, 0);											/* ADDITIONAL count */

	return (-1);
}
/*--- _formerr_internal() -----------------------------------------------------------------------*/


/**************************************************************************************************
	_DNSERROR_INTERNAL
	Generate error response for query and set status to NEED_SEND.  Always returns -1, as a
	convenience.
**************************************************************************************************/
int
_dnserror_internal(
	TASK *t,					/* The failed task */
	dns_rcode_t rcode,	/* The return code to use, such as DNS_R_SERVFAIL, etc. */
	task_error_t reason,	/* Further explanation of the error */
	const char *filename,
	unsigned int lineno
)
{
	if (t->hdr.rcode == DNS_R_NOERROR)
	{
#if DEBUG_ENABLED
		Debug("%s: dnserror(): %s %s from %s:%u",
				desctask(t), mydns_rcode_str(rcode), err_reason_str(reason), filename, lineno);
#endif
		t->hdr.rcode = rcode;
		t->status = NEED_WRITE;
		t->reason = reason;
	}

	return (-1);
}
/*--- _dnserror_internal() ----------------------------------------------------------------------*/

/* vi:set ts=3: */
/* NEED_PO */
